<?php
namespace Socks5;
use Net\Event;

trait Socks5Trait {
    
    public $VER = 5;
    
    public $METHOD_ANONYMOUS  = 0;
    public $METHOD_GSSAPI  = 0x1;
    public $METHOD_USERPASSWORD  = 0x2;
    public $METHOD_NONE  = 0xFF;
    
    public $ADDRESS_TYPE_IPV4=1;
    public $ADDRESS_TYPE_DOMAINNAME=3;
    public $ADDRESS_TYPE_IPV6=4;
    
    public $CMD_CONNECT = 1;
    public $CMD_BIND = 2;
    public $CMD_UDP = 3;
    
    public $ERROR_HANDSHAKE_VERSION='HANDSHAKE_VERSION';
    
    public $REP_TYPE_SUCCESS = 0;
    public $REP_TYPE_SOCK_SERVER_FAIL = 1;
    public $REP_TYPE_CONNECTION_NOT_ALLOW = 2;
    public $REP_TYPE_NETWORK_UNREACHABLE = 3;
    public $REP_TYPE_HOST_UNREACHABLE = 4;
    public $REP_TYPE_CONNECTION_REFUSED = 5;
    public $REP_TYPE_TTL_EXPIRED = 6;
    public $REP_TYPE_COMMAND_NOT_SUPPORTED = 7;
    public $REP_TYPE_ADDRESS_TYPE_NOT_SUPPORT = 8;
    
    protected function _parseHandshakePackage($str) {
        $version = ord($str[0]);
        $methodLength = ord($str[1]);
        $methods = substr($str, 2, $methodLength);
        $methodsAry = array_map('ord', str_split($methods, 1));
        
        return [
            'version' => $version,
            'method_length' => $methodLength,
            'support_methods' => $methodsAry
        ];
    }
    
    protected function _parseRequestPackage($str) {
        $version = ord($str[0]);
        $cmd = ord($str[1]);
        $addressType = ord($str[3]);
        
        $result = [
            'version' => $version,
            'cmd' => $cmd,
            'address_type' => $addressType,
        ];
        
        if($addressType == $this->ADDRESS_TYPE_IPV4) {
            //版本号,命令码, 保留地址, 地址类型, ip地址(4字节), 端口字节1, 端口字节2
            $address = implode('.', array_map('ord', str_split(substr($str, 4, 4), 1)));
            $port = (ord($str[8]) << 8) + ord($str[9]);
    
            $result['address'] = $address;
            $result['port'] = $port;
        } else if($addressType == $this->ADDRESS_TYPE_DOMAINNAME) {
            //版本号,命令码, 保留地址, 地址类型, 域名长度(n), 域名(n字节), 端口字节1, 端口字节2
            $length = ord($str[4]);
            $domain = substr($str, 5, $length);
            $port = (ord($str[5+$length]) << 8) + ord($str[6+$length]);
            
            $result['domain'] = $domain;
            $result['port'] = $port;
        }
        
        return $result;
    }
}